<?php

declare(strict_types=1);

namespace App\AdminApi\Module\Admin\Service;

use App\AdminApi\Module\Admin\Enums\UserEnums;
use App\Common\Guard\AdminGuard;
use App\Common\Model\Admin\UserModel;
use App\Sys;
use Zms\AdminElementPlus\FormCreate\Form;
use Zms\AdminElementPlus\FormCreate\FormItem;
use Zms\Basics\BasicsModel;
use Zms\Basics\BasicsServe;
use Zms\Exception\AppException;
use Zms\Exception\FormException;
use Zms\PasswordVerifier\PasswordVerifier;
use Zms\Unit\Lists;

class UserService extends BasicsServe
{
    /**
     * @return UserModel::class
     */
    public static function model(): string
    {
        return UserModel::class;
    }


    /**
     * 是否是根账号
     * @param int $id
     * @return bool
     */
    public function isRootUser(int $id): bool
    {
        return $id === 1;
    }


    /**
     * 检查账号状态
     * @param int|UserModel $user
     * @return bool|string
     */
    public function checkAccountStatus(int|UserModel $user): bool|string
    {
        if (!($user instanceof UserModel)) {
            $user = $this->search(['id' => $user])->first();
        }
        if (!$user) return '账号已失效';
        if ($user->status === UserEnums::STATUS_STOP) {
            return '此账号已禁用';
        }
        if ($user->locking > time()) {
            return '此账号当前已被锁定';
        }
        return true;
    }


    /**
     * @param array $values
     * @return BasicsModel|false
     * @throws AppException
     */
    public function created(array $values): BasicsModel|false
    {
        if (isset($values['account'])) {
            if ($this->search(['account' => $values['account']])->exists()) {
                throw new AppException("账号'{$values['account']}'已被使用,请更换账号");
            }
        }
        $guard = (new AdminGuard);
        $values['secret_key'] = $guard->generateSecretKey();
        if (isset($values['password'])) {
            $error = $this->checkPassword($values['password']);
            if ($error !== true) {
                throw new AppException($error);
            }
            $values['password'] = $guard->generatePassword($values['password'], $values['secret_key']);
        }
        return parent::created($values);
    }


    /**
     * 更新数据
     * @param array $data
     * @param array|null|string $where
     * @param bool $returnModel
     * @return bool|BasicsModel
     * @throws AppException
     */
    public function updated(array $data, null|array|string $where = null, bool $returnModel = false): bool|BasicsModel
    {
        if (isset($data['account']) && isset($data['id'])) {
            if ($this->search(['account' => $data['account']])->whereRaw("`id` != ?", [$data['id']])->exists()) {
                throw new AppException("账号'{$data['account']}'已被使用,请更换账号");
            }
        }
        if (isset($data['password'])) {
            if (strlen($data['password']) > 0) {
                $data['secret_key'] = (new AdminGuard)->generateSecretKey();
                $error = $this->checkPassword($data['password']);
                if ($error !== true) {
                    throw new AppException($error);
                }
                $data['password'] = (new AdminGuard)->generatePassword($data['password'], $data['secret_key']);
            } else {
                unset($data['secret_key']);
                unset($data['password']);
            }
        }
        return parent::updated($data, $where, $returnModel);
    }


    /**
     * 密码规则检测
     * @param string $password
     * @return bool|string
     */
    public function checkPassword(string $password): bool|string
    {
        $min_length = intval(Sys::conf('admimpwd.min_length', 5) ?: 5);
        $max_length = intval(Sys::conf('admimpwd.max_length', 30) ?: 30);
        $element = Sys::conf('admimpwd.element');
        $verifier = new PasswordVerifier(['min_length' => $min_length, 'max_length' => $max_length, 'element' => is_array($element) ? $element : []]);
        if ($verifier->verifier($password) === false) {
            return $verifier->getError();
        }
        return true;
    }


    /**
     * 创建管理员表单
     * @return Form
     * @throws FormException
     */
    public function createdUserForm(): Form
    {
        $rule[] = FormItem::Input('nickname', '管理员昵称')->clearable(true)->maxlength(20)->required('请输入管理员昵称');
        $rule[] = FormItem::Input('account', '登录账号')->placeholder('后台登录账号')->clearable(true)->required('请输入后台登录账号')->maxlength(30);
        $rule[] = FormItem::Input('password', '登录密码')->placeholder('后台登录密码')->maxlength(30)->required('请输入登录密码')->clearable(true);
        $rule[] = FormItem::ImageInput('avatar', '账号头像')->required('请设置账号头像')->clearable(true);
        $rule[] = FormItem::Cascader('department_id', '所属部门')->options(Sys::container(DepartmentService::class)->getTreeFormData())->checkStrictly(true)->valueKey('id')->labelKey('name')->clearable(true);
        $rule[] = FormItem::Select('job_id', '所在职位')->options(Sys::container(JobService::class)->JobFormData())->clearable(true);
        $rule[] = FormItem::Switchs('is_super', '超级权限', (string)UserEnums::SUPER_NO)->hint('选择后此管理员将拥有所有操作权限');
        $rule[] = FormItem::SelectMuliple('role_id', '权限角色')->required('请为此管理员分配角色')->multipleLimit(3)->filterable(false)->clearable(true)->options(Sys::container(RoleService::class)->roleFormData())->hint('最多可选三个角色');
        $rule[] = FormItem::Radio('data_auth_type', '数据权限', UserEnums::DATA_AUTH_TYPE_SELF)->options(UserEnums::Datas(UserEnums::TAG['DATA_AUTH_TYPE']))->required('请给管理员分配数据权限')->control([
            [
                'value' => UserEnums::DATA_AUTH_TYPE_DEP,
                'rule' => [
                    FormItem::Cascader('auth_dep', '授权部门')->options(Sys::container(DepartmentService::class)->getTreeFormData())->checkStrictly(true)->valueKey('id')->multiple(true)->labelKey('name')->clearable(true)->required('请选择部门')->hint('查看本人和指定部门的数据权限')
                ]
            ]
        ])->hint("超级管理员或超级权限拥有所有数据权限,【本人】仅能查看操作本人的数据,【本部门】可查看当前部门权限,当账号为部门负责人时可同时查看下级部门数据,【指定部门】查看本人和指定部门的数据权限,【我管理的部门】查看所有我管理的部门和下级部门");
        return Form::create('添加管理员')->setRules($rule)->setOptionFormInline(true);
    }


    /**
     * 编辑管理员表单
     * @param string $id
     * @return Form
     * @throws AppException
     */
    public function updatedUserForm(string $id = ''): Form
    {
        /**
         * @var UserModel $user
         */
        $user = $this->search(['id' => $id])->first();
        if ($id && $user) {
            $dep = Sys::container(DepartmentService::class)->getArchitectureIds($user->department_id);
            $rule[] = FormItem::Hidden('id', $id);
            $rule[] = FormItem::Input('nickname', '管理员昵称', $user->nickname)->clearable(true)->maxlength(20)->required('请输入管理员昵称');
            $rule[] = FormItem::Input('account', '登录账号', $user->account)->placeholder('后台登录账号')->clearable(true)->required('请输入后台登录账号')->maxlength(30);
            $rule[] = FormItem::Input('password', '登录密码')->placeholder('后台登录密码')->maxlength(30)->hint('不填写则代表不更改')->clearable(true);
            $rule[] = FormItem::ImageInput('avatar', '账号头像', $user->avatar)->required('请设置账号头像')->clearable(true);
            $rule[] = FormItem::Cascader('department_id', '所属部门', Lists::toStringList($dep))->options(Sys::container(DepartmentService::class)->getTreeFormData())->checkStrictly(true)->valueKey('id')->labelKey('name')->clearable(true);
            $rule[] = FormItem::Select('job_id', '所在职位', strval($user->job_id ? $user->job_id : ''))->options(Sys::container(JobService::class)->JobFormData())->clearable(true);
            if ($user->id !== 1) {
                $rule[] = FormItem::Switchs('is_super', '超级权限', $user->is_super ? '1' : '0')->hint('选择后此管理员将拥有所有操作权限');
                $rule[] = FormItem::SelectMuliple('role_id', '权限角色', Lists::toStringList($user->role_id))->required('请为此管理员分配角色')->multipleLimit(3)->filterable(false)->clearable(true)->options(Sys::container(RoleService::class)->roleFormData())->hint('最多可选三个角色');
                $rule[] = FormItem::Radio('data_auth_type', '数据权限', $user->data_auth_type)
                    ->options(UserEnums::Datas(UserEnums::TAG['DATA_AUTH_TYPE']))
                    ->required('请给管理员分配数据权限')
                    ->control([
                        [
                            'value' => UserEnums::DATA_AUTH_TYPE_DEP,
                            'rule' => [
                                FormItem::Cascader('auth_dep', '授权部门', $user->auth_dep)->options(Sys::container(DepartmentService::class)->getTreeFormData())->checkStrictly(true)->valueKey('id')->multiple(true)->labelKey('name')->clearable(true)->required('请选择部门')->hint('查看本人和指定部门的数据权限')
                            ]
                        ]
                    ])
                    ->hint("超级管理员或超级权限拥有所有数据权限,【本人】仅能查看操作本人的数据,【本部门】可查看当前部门权限,当账号为部门负责人时可同时查看下级部门数据,【指定部门】查看本人和指定部门的数据权限,【我管理的部门】查看所有我管理的部门和下级部门");
            } else {
                $rule[] = FormItem::Hidden('role_id', ['*']);
            }
            return Form::create('编辑管理员')->setRules($rule)->setOptionFormInline(true);
        }
        throw new AppException('帐号不存在或已删除');
    }
}